package org.cqu_proj.demo.service;

import org.cqu_proj.demo.dao.MovieFeaturesRepository;
import org.cqu_proj.demo.entity.MovieFeatures;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class MovieFeaturesService {
    public final MovieFeaturesRepository movieFeaturesRepository;
    @Autowired

    public MovieFeaturesService(MovieFeaturesRepository movieFeaturesRepositor) {
        this.movieFeaturesRepository = movieFeaturesRepositor;
    }
    //features工具
    // 查询电影特征并将其转为列表
    public List<Double> getMovieFeaturesAsList(int movieId) {

        MovieFeatures movieFeatures = movieFeaturesRepository.findByMovieId(movieId);

        if (movieFeatures == null) {
            throw new IllegalArgumentException("Movie with ID " + movieId + " not found.");
        }

        // <editor-fold desc="笨拙的映射方法">
        List<Double> featuresList = new ArrayList<>();
        featuresList.add(movieFeatures.getFeature1());
        featuresList.add(movieFeatures.getFeature2());
        featuresList.add(movieFeatures.getFeature3());
        featuresList.add(movieFeatures.getFeature4());
        featuresList.add(movieFeatures.getFeature5());
        featuresList.add(movieFeatures.getFeature6());
        featuresList.add(movieFeatures.getFeature7());
        featuresList.add(movieFeatures.getFeature8());
        featuresList.add(movieFeatures.getFeature9());
        featuresList.add(movieFeatures.getFeature10());
        featuresList.add(movieFeatures.getFeature11());
        featuresList.add(movieFeatures.getFeature12());
        featuresList.add(movieFeatures.getFeature13());
        featuresList.add(movieFeatures.getFeature14());
        featuresList.add(movieFeatures.getFeature15());
        featuresList.add(movieFeatures.getFeature16());
        featuresList.add(movieFeatures.getFeature17());
        featuresList.add(movieFeatures.getFeature18());
        featuresList.add(movieFeatures.getFeature19());
        featuresList.add(movieFeatures.getFeature20());
        // </editor-fold>

        return featuresList;
    }

    // 实现 SGD 方法
    public List<Double> sgdForUserFeatures(
            List<Double> userFeatures,
            List<Double> movieFeatures,
            double targetRating,
            double learningRate,
            int epochs) {

        if (userFeatures.size() != movieFeatures.size()) {
            throw new IllegalArgumentException("User and movie features must have the same size.");
        }

        for (int epoch = 0; epoch < epochs; epoch++) {
            // 计算点积
            double dotProduct = 0;
            for (int i = 0; i < userFeatures.size(); i++) {
                dotProduct += userFeatures.get(i) * movieFeatures.get(i);
            }

            // 计算误差
            double error = dotProduct - targetRating;

            // 如果误差足够小，提前停止
            if (Math.abs(error) < 0.2) {
                System.out.println("Epoch " + (epoch + 1) + ": Early stop, error is small enough.");
                break;
            }

            // 更新 userFeatures
            for (int i = 0; i < userFeatures.size(); i++) {
                double gradient = error * movieFeatures.get(i);
                userFeatures.set(i, userFeatures.get(i) - learningRate * gradient);
            }

            // 打印损失值
            double loss = Math.pow(error, 2) / 2;
            System.out.println("Epoch " + (epoch + 1) + ": Loss = " + loss);
        }

        return userFeatures;
    }

}
